from flask import (
    Blueprint,
    views,
    render_template,
    make_response,
    request,
    session,
    url_for,
    g,
    abort,
    redirect
)
from utils.captcha import Captcha
from utils import zlcache,restful,safeutils
from exts import mail,db
import random
import string
# 二进制字节流
from io import BytesIO
from flask_mail import Message
from .forms import SignupFrom,SigninForm,AddPostForm,AddCommentForm
from .models import FrontUser
import config
from ..models import BannerModel,BoardModel,PostModel,CommentModel,HighlightModel
from .decorators import login_required
from flask_paginate import Pagination,get_page_parameter
from sqlalchemy.sql import func


bp = Blueprint("front",__name__)

@bp.route('/')
def index():
    board_id = request.args.get('bd',type=int,default=None)
    page = request.args.get(get_page_parameter(),type=int,default=1)
    sort = request.args.get('st',type=int,default=1)

    banners = BannerModel.query.order_by(BannerModel.priority.desc()).limit(4)
    boards = BoardModel.query.all()
    start = (page-1)*config.PER_PAGE
    end = start + config.PER_PAGE
    pasts = None
    total = 0
    query_obj = None
    if sort == 1:
        query_obj = PostModel.query.order_by(PostModel.create_time.desc())
    elif sort == 2:
        # 按照加精的时间排序
        query_obj = db.session.query(PostModel).outerjoin(HighlightModel).order_by(HighlightModel.create_time.desc(),PostModel.create_time.desc())
    elif sort == 3:
        # 按照点赞数量排序
        query_obj = PostModel.query.order_by(PostModel.create_time.desc())
    elif sort == 4:
        # 按照评论数量排序
        query_obj = db.session.query(PostModel).outerjoin(CommentModel).group_by(PostModel.id).order_by(func.count(CommentModel.id).desc(),PostModel.create_time.desc())

    if board_id:
        query_obj = query_obj.filter(PostModel.borad_id==board_id)
        posts = query_obj.slice(start,end)
        total = query_obj.count()
    else:
        posts = query_obj.slice(start,end)
        total = query_obj.count()
    pagination = Pagination(bs_version=3,page=page,total=total,outer_window=0,inner_window=2)
    content ={
        'banners': banners,
        'boards': boards,
        'posts': posts,
        'pagination':pagination,
        'current_board':board_id,
        'current_sort':sort
    }
    return render_template("front/front_index.html",**content)


@bp.route('/logout/')
def logout():
    del session[config.FRONT_USER_ID]
    return redirect('/')


# 用户注测页面
class SignupView(views.MethodView):
    def get(self):
        return_to = request.referrer
        if return_to and return_to != request.url and safeutils.is_safe_url(return_to):
            return render_template("front/front_signup.html",return_to=return_to)
        else:
            return render_template("front/front_signup.html")

    def post(self):
        form = SignupFrom(request.form)
        if form.validate():
            email = form.email.data
            username = form.username.data
            password = form.password1.data
            user = FrontUser(email=email,username=username,password=password)
            db.session.add(user)
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error(message=form.get_error())

bp.add_url_rule('/signup/',view_func=SignupView.as_view('signup'))


# 用户登录页面
class SigninView(views.MethodView):
    def get(self):
        return_to = request.referrer
        if return_to and return_to != request.url and return_to != url_for("front.signup") and safeutils.is_safe_url(return_to):
            return render_template("front/front_signin.html",return_to=return_to)
        else:
            return render_template("front/front_signin.html")

    def post(self):
        form = SigninForm(request.form)
        if form.validate():
            email = form.email.data
            password = form.password.data
            remember = form.remember.data
            user = FrontUser.query.filter_by(email=email).first()
            if user and user.check_password(password):
                session[config.FRONT_USER_ID] = user.id
                if remember:
                    session.permanent = True
                return restful.success()
            else:
                restful.params_error("邮箱或密码错误！")
        else:
            return restful.params_error(message=form.get_error())


bp.add_url_rule('/signin/',view_func=SigninView.as_view('signin'))

# 图形验证码上传至浏览器
@bp.route('/captcha/')
def graph_captcha():
    text,image = Captcha.gene_graph_captcha()
    zlcache.set(text.lower(),text.lower())
    out = BytesIO()
    image.save(out, 'png')
    out.seek(0)
    resp = make_response(out.read())
    resp.content_type = 'image/png'
    return resp


# 邮箱验证码
@bp.route('/email_captcha/')
def email_captcha():
    email = request.args.get('email')
    if not email:
        return restful.params_error("请输入邮箱账号")
    source = list(string.ascii_letters)
    source.extend(map(lambda x:str(x),range(0,10)))
    captcha="".join(random.sample(source,6))
    message = Message('Python论坛邮箱验证码',recipients=[email],body='您的验证码是：%s'%captcha)
    try:
        mail.send(message)
    except:
        return restful.server_error()
    zlcache.set(email,captcha)
    return restful.success()


@bp.route('/apost/',methods=['GET','POST'])
@login_required
def apost():
    if request.method == 'GET':
        board = BoardModel.query.all()
        return render_template("front/front_apost.html",boards=board)
    else:
        form = AddPostForm(request.form)
        if form.validate():
            title = form.title.data
            content = form.content.data
            board_id = form.board_id.data
            board = BoardModel.query.get(board_id)
            author = g.front_user
            if not board:
                return restful.params_error("没有这个板块！")
            post = PostModel(title=title,content=content,borad_id=board_id,author=author)
            db.session.add(post)
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error(message=form.get_error())


@bp.route('/p/<post_id>')
def post_detail(post_id):
    post = PostModel.query.get(post_id)
    # comment_count = db.session.query(PostModel).filter(PostModel.id == post_id).join(CommentModel).count()
    comment_count = post.comment_count
    post.read_count = post.read_count + 1
    db.session.commit()
    # if not post:
    #     abort(404)
    return render_template("front/front_pdetail.html",post=post,comment_count=comment_count)


@bp.route('/acomment/',methods=['POST'])
@login_required
def add_comment():
    form = AddCommentForm(request.form)
    if form.validate():
        content = form.content.data
        post_id = form.post_id.data
        post = PostModel.query.get(post_id)
        if post:
            comment = CommentModel(content=content)
            comment.post = post
            comment.author = g.front_user
            post.comment_count += 1
            db.session.add(comment)
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error("没有这篇帖子")
    else:
        return restful.params_error(form.get_error())


@bp.route('/profile/')
def profile():
    return render_template("front/front_profile.html")